package com.jingdianjichi.club.gateway.exception;

import cn.dev33.satoken.exception.SaTokenException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jingdianjichi.club.gateway.entity.Result;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 网关全局异常处理
 * 用于处理在Spring WebFlux项目中通过网关进行请求转发时发生的所有异常。
 * 实现了ErrorWebExceptionHandler接口，允许自定义异常处理逻辑。
 *
 * @author: WuYimin
 * Date: 2024-02-08
 */
@Component // 表示这是一个组件，由Spring管理
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {

	private ObjectMapper objectMapper = new ObjectMapper(); // 用于将对象序列化为JSON字符串

	@Override
	public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
		// 获取当前请求和响应对象
		ServerHttpRequest request = serverWebExchange.getRequest();
		ServerHttpResponse response = serverWebExchange.getResponse();

		// 初始化状态码和错误信息
		Integer code = 200; // HTTP状态码
		String message = ""; // 错误信息
		// 判断异常类型，根据不同的异常类型设置不同的响应状态码和错误信息
		if (throwable instanceof SaTokenException) {
			code = 401; // 对于SaTokenException异常，设置状态码为401，表示权限问题
			message = "用户无权限"; // 设置具体的错误信息
			throwable.printStackTrace(); // 打印堆栈信息，便于调试
		} else {
			code = 500; // 对于其他异常，设置状态码为500，表示服务器内部错误
			message = "系统繁忙"; // 设置具体的错误信息
			throwable.printStackTrace(); // 打印堆栈信息，便于调试
		}
		// 构造响应结果对象
		Result result = Result.fail(code, message);
		// 设置响应的内容类型为JSON
		response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
		// 写入响应数据
		return response.writeWith(Mono.fromSupplier(() -> {
			DataBufferFactory dataBufferFactory = response.bufferFactory();
			byte[] bytes = null;
			try {
				// 将结果对象序列化为JSON字符串的字节数组
				bytes = objectMapper.writeValueAsBytes(result);
			} catch (JsonProcessingException e) {
				e.printStackTrace(); // 序列化失败时打印异常堆栈信息
			}
			// 使用响应的bufferFactory来包装字节数组，并写入响应中
			return dataBufferFactory.wrap(bytes);
		}));
	}
}
